package com.dk.controller;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.dk.config.AlipayConfig;
import com.dk.data.ContentRedisConstant;
import com.dk.service.ITOrderService;
import org.apache.catalina.User;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
 * 项目名: dongdongshop_parent
 * 类名: AlipayController
 * 描述: 支付宝的同步回调和异步回调
 * 创建者: zjg
 * 创建时间: 2021-09-22 18:07:30
 **/
@RequestMapping("alipay")
@Controller
public class AlipayController {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private ITOrderService itOrderService;
    //支付完成同步回调,最后跳转自己定义成功页面
    @RequestMapping("returnUrl")
    public String returnUrl(Model model,HttpServletRequest request, String out_trade_no, String trade_no, String total_amount) throws AlipayApiException {
        /* *
         * 功能：支付宝服务器同步通知页面
         * 日期：2017-03-30
         * 参数： 商户订单号/支付宝交易号/付款金额
         */
        //获取支付宝GET过来反馈信息
        System.out.println("进入同步回调方法");
        boolean signVerified = isSignVerified(request);
        //如果验签成功,说明数字签名没有被篡改过,如果失败两种可能:1.篡改过; 2.编码格式问题导致乱码或者数据丢失
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        if(signVerified) {
            System.out.println("同步验签成功>>>>>>>>>>>>");
            model.addAttribute("user",user);
            model.addAttribute("out_trade_no",out_trade_no);
            model.addAttribute("trade_no",trade_no);
            model.addAttribute("total_amount",total_amount);
            //跳转自己支付成功页面
            return "paysuccess";
        }else {
            System.out.println("同步验签失败>>>>>>>>>>>>");
            model.addAttribute("user",user);
            return "payfail";
        }
    }
    //异步回调
    @RequestMapping("notifyUrl")
    @ResponseBody
    public String notifyUrl(HttpServletRequest request, String out_trade_no, String trade_no, String trade_status) throws AlipayApiException {
        /* *
         * 功能：支付宝服务器异步通知页面
         * 日期：2017-03-30
         * 说明：商户订单号/支付宝交易号/支付宝支付状态
         *************************页面功能说明*************************
         */
        //获取支付宝POST过来反馈信息
        System.out.println("进入异步回调方法");
//       验签方法
        boolean signVerified = isSignVerified(request);
        //验签成功
        if(signVerified) {
//          支付页,用户取消交易会进入下面
            if(trade_status.equals("TRADE_FINISHED")){
                System.out.println("用户未支付,取消支付");
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                //如果有做过处理，不执行商户的业务程序
                //注意：
                //退款日期超过可退款期限后（如三个月可退款），支付宝系统发送该交易状态通知
//            支付成功或部分退款成功都会进入下面,因为部分退款交易状态还是成功状态
            }else if (trade_status.equals("TRADE_SUCCESS")){
                //判断该笔订单是否在商户网站中已经做过处理(解决幂等性问题,否则遇到问题支付宝会自动重试,重复执行业务逻辑,比如重复加积分)
                //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
//                借助redis,经已经处理过的订单号或者流水号存放到redis,下次再进判断redis是否存在该订单
                String[] gmt_refunds = request.getParameterMap().get("gmt_refund");
                Long momOrderId = Long.parseLong(out_trade_no);// 总订单号/母订单号
//                通过退款独有的参数字段gmt_refund判断进来的是 退款 还是支付
                if(gmt_refunds == null){ // 进来的是支付逻辑业务
                    System.out.println("进入支付逻辑业务处理");
                    if (!redisTemplate.boundHashOps(ContentRedisConstant.ALIPAY).hasKey(trade_no)){
//                    根据母订单号查询出商家订单order 和sku订单orderItem,将流水号赋给每一个订单,方便后面退款查询
//                        List<TOrder> orderList = itOrderService.selectOrderByMomOrderId(momOrderId);
//                        List<TbOrderItem> orderItemList = orderService.selectItemByMomOrderId(momOrderId);
////                    修改商家订单状态,并将支付宝流水号放进订单字段中
//                        for (TbOrder order : orderList) {
//                            order.setStatus("2");//已付款
//                            order.setTradeNo(trade_no);
//                            orderService.updateOrder(order);
//                        }
//                        for (TbOrderItem orderItem : orderItemList) {
//                            orderItem.setTradeNo(trade_no);
//                            orderService.updateOrderItem(orderItem);
                        }
//                    将该支付订单存入redis(键为支付流水号,值为母订单号)
                        redisTemplate.boundHashOps(ContentRedisConstant.ALIPAY).put(trade_no,out_trade_no);
                    }//如果有做过处理，不执行商户的业务程序

                }else { // 进来的是退款成功
                    System.out.println("进入部分退款逻辑业务处理");
//                    if (!redisTemplate.boundHashOps(ContentRedisConstant.REFUND).hasKey(trade_no)){
//                        List<TOrder> orderList = orderService.selectOrderByMomOrderId(momOrderId);
////                        List<TbOrderItem> orderItemList = orderService.selectItemByMomOrderId(momOrderId);
//////                    修改商家订单状态,
//                        for (TbOrder order : orderList) {
//                            order.setStatus("6");//交易关闭
//                            orderService.updateOrder(order);
//                        }
//                        for (TbOrderItem orderItem : orderItemList) {
//                            orderItem.setTradeNo(trade_no);
//                            orderService.updateOrderItem(orderItem);
//                        }
////                    将该支付订单存入redis(键为支付流水号,值为母订单号)
                        redisTemplate.boundHashOps(ContentRedisConstant.REFUND).put(trade_no,out_trade_no);
                    }//如果有做过处理，不执行商户的业务程序

                    //注意：
                    //付款完成后，支付宝系统发送该交易状态通知
                }
//            }
            System.out.println("异步验签成功>>>>>>>");
           return "success";

//        }else {//验证失败
//            System.out.println("异步验签失败>>>>>>>");
//            return "fail";

            //调试用，写文本函数记录程序运行情况是否正常
            //String sWord = AlipaySignature.getSignCheckContentV1(params);
            //AlipayConfig.logResult(sWord);
        }
//    }

    //    验签方法封装
    private boolean isSignVerified(HttpServletRequest request) throws AlipayApiException {
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用
//            valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
//        验证数字签名(验签)
        return AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type);
    }

////    退款
//    @RequestMapping("tradeRefund")
//    @ResponseBody
//    public Result tradeRefund(String out_trade_no,String trade_no,String refund_amount,String out_request_no, String refund_reason) throws AlipayApiException {
//        System.out.println("进入退款方法");
//        //获得初始化的AlipayClient
//        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);
//
//        //设置请求参数
//        AlipayTradeRefundRequest alipayRequest = new AlipayTradeRefundRequest();
//
//        alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
//                + "\"trade_no\":\""+ trade_no +"\","
//                + "\"refund_amount\":\""+ refund_amount +"\","
//                + "\"refund_reason\":\""+ refund_reason +"\","
//                + "\"out_request_no\":\""+ out_request_no +"\"}");
//
//        //请求
//        String result = alipayClient.execute(alipayRequest).getBody();
//        if (result != null){
//            System.out.println(result);
//            return Result.build(ResultEnum.SUCCESS);
//        }
//        return Result.build(ResultEnum.ERROR);
//    }

}
